<?php
namespace ChannelThrift\Service;

use Base\BaseService;
use \Common\Org\PhpRedis;
use \Services\AuctionService\InvalidException;

class OrderService extends BaseService {
    Protected $autoCheckFields = false;
    public  $connection = 'DB_AUMS';
    public $tablePrefix = 'au_';


    /**
     * 获取单个订单
     * @param integer $orderID
     * @return array
     */
    public function getOrder($orderID)
    {
        if (empty($orderID)) {
            return false;
        }
        return D('ChannelThrift/Aums/Order')->where("order_id = '" . $orderID."'")->find();
    }

    /**
     * 获取单个订单
     * @param array $map
     * @param string $orderBy
     * @return array
     */
    public function getOrderByMap($map,$orderBy='order_id DESC',$limit='')
    {
        if (empty($map)) {
            return false;
        }
        if($limit){
            $rs = D('ChannelThrift/Aums/Order')->where($map)->order($orderBy)->limit($limit)->select();
        }else{
            $rs = D('ChannelThrift/Aums/Order')->where($map)->order($orderBy)->find();
        }
        return $rs;
    }

    /**
     * 获取单个订单
     * @param array $map
     * @return array
     */
    public function getOrders($map)
    {
        if (empty($map)) {
            return false;
        }
        return D('ChannelThrift/Aums/Order')->where($map)->select();
    }

    /**
     * 更新拍单
     *
     * @param int $orderId
     * @param array $info
     * @param array $map
     *
     * @return boolean
     */
    public function update($orderId,$info, $map = array())
    {
        if (empty($map)) {
            $map['order_id'] = array('eq', $orderId);
        }
        $info['last_time'] = date('Y-m-d H:i:s');
        $rs =  D('ChannelThrift/Aums/Order')->where($map)->save($info);
        return $rs;
    }

    public function updateBySceneId($sceneId,$data){
        $data['last_time'] = date('Y-m-d H:i:s');
        $map = ['scene_id'=>['eq',$sceneId],'status'=>['eq',3]];
        return D('ChannelThrift/Aums/Order')->where($map)->save($data);

    }
    /**
     * 获取冻结信息
     * @param integer $orderID
     * @return string
     */
    public function getFreezeDetail($orderID)
    {
        if (empty($orderID)) {
            return false;
        }
        $sql = "SELECT CONCAT('对拍品【',order_no,',',".$orderID.",'】 ',' 进行出价，冻结保证金。') msg FROM  au_order WHERE  `order_id` = '".$orderID."'";
        return $this->query($sql);
    }

    /**
     * 获取解冻信息
     * @param integer $orderID
     * @return string
     */
    public function getUnfreezeDetail($orderID)
    {
        if (empty($orderID)) {
            return false;
        }
        $sql = "SELECT CONCAT('解冻出价保证金，拍品【',order_no,',',".$orderID.",'】 ',' 。') msg FROM  au_order WHERE  `order_id` = '".$orderID."'";
        return $this->query($sql);
    }

    /**
     * 获得出价信息
     * @param $orderID
     */
    public function getBiddingInfo($order_id){

        $sql = "SELECT o.order_id,o.order_no,o.bid_start_price,o.bid_best_price,o.bidding_best_price,o.bid_best_dealer_id,o.transfer_fee,o.act_elapsed_time,o.est_elapsed_time,o.bidding_start_time,os.starttime
        ,o.bidding_best_dealer_id,IF(o.bidding_best_price=0,o.bid_start_price,o.bidding_best_price) as price
        ,UNIX_TIMESTAMP(o.bidding_start_time)+IF(o.act_elapsed_time>o.est_elapsed_time,o.act_elapsed_time,o.est_elapsed_time) - UNIX_TIMESTAMP(NOW()) AS left_time
        FROM au_order o INNER join au_order_scene os on os.scene_id = o.scene_id WHERE o.order_id='".$order_id."'";
        $r1 = $this->query($sql);
        if ($r1[0]['left_time'] <= 0)
            $r1[0]['left_time'] = 0;
        $sql = "SELECT COUNT(*) AS bidding_num,COUNT(DISTINCT dealer_id ) AS dealer_num  FROM au_bidding_log WHERE order_id='".$order_id."'";
        $r2 = $this->query($sql);
        $bidding_info = (array_merge($r1[0], $r2[0]));
        $bidding_info['starttime'] = intval(strtotime($bidding_info['starttime']))*1000;
        $bidding_info['bidding_start_time'] = intval(strtotime($bidding_info['bidding_start_time']))*1000;
        $bidding_info['act_elapsed_time'] = intval($bidding_info['act_elapsed_time'])*1000;
        $bidding_info['est_elapsed_time'] = intval($bidding_info['est_elapsed_time'])*1000;
        return $bidding_info;
    }

    /**
     * 设置修改信息
     * @param $where array 条件
     * @param $data array  修改内容
     * @return bool
     */
    public function setOrderInfo($where=array(),$data=array()){
        return D('ChannelThrift/Aums/Order')->where($where)->save( $data );
    }

    /**
     * 判断定时单开拍时间是否合法(定时单必须大于等于场开始时间，
     * 若场已开始则开拍时间必须介于大于当前时间5分钟和小于结束时间前5分钟之间)
     * @param int $sceneId
     * @param int $biddingStartTime
     * @return bool
     */
    public function checkBiddingStartTime($sceneId, $biddingStartTime){
        $scene = new SceneService();
        $map = array('scene_id'=>array('eq',$sceneId));
        $sceneDetail = $scene->getSceneInfo($map);

        if ($biddingStartTime < strtotime($sceneDetail['starttime'])
            || date('Y-m-d', $biddingStartTime) != date('Y-m-d', strtotime($sceneDetail['starttime']))) {
            return false;
        }
        switch($sceneDetail['status']){
            case '2':
                $time1 = time()+5*60;
                $time2 = $this->getEstimatedEndtime($sceneId)-5*60;//场内最后一个拍单的预计结束时间-5*60
                if($biddingStartTime<$time1 || $biddingStartTime >$time2){
                    trace('定时单上拍时间不在'.$time1.'和'.$time2.'之间','','ERR',true);
                    return false;
                }
                break;
            case '3':
                trace('场已结束上拍失败','','ERR',true);
                return false;
            break;
        }

        return true;
    }

    /**
     * 获取场内最后一个拍单的预计结束时间
     * @param $sceneId
     * @return int
     */
    private function getEstimatedEndtime($sceneId){
        $map = ['scene_id'=>$sceneId];
        $order=$this->getOrderByMap($map,'bidding_start_time DESC');
        return strtotime($order['bidding_start_time'])+$order['est_elapsed_time'];
    }
    /**
     * 计算顺序单开拍时间
     * @param $sceneId string 场ID
     * @return mixed
     */
    public function getBiddingStartTime($sceneId)
    {
        $scene = new SceneService();
        $map = array('scene_id'=>array('eq',$sceneId));
        $sceneDetail = $scene->getSceneInfo($map);
        $timeOffset = strtotime($sceneDetail['starttime']);

        $map = array();
        $map['scene_id'] = array('eq',$sceneId);
        $map['rank'] = array('gt',0);
        $map['is_timing_order'] = array('eq',0);
        $map['status'] = array('not in','2,6,12');
        $orders = $this->getOrders($map);
        $timeOffset1 = 0;
        foreach ($orders as $k => $v) {
            $timeOffset1 += $v['est_elapsed_time'];
        }
        return date('Y-m-d H:i:0', $timeOffset + $timeOffset1);
    }

    /**
     * 重新排序场次内拍单顺序
     * @param array $order 拍单详情
     * @return bool
     */
    public function resetOrderRank($order)
    {
        $m = D('ChannelThrift/Aums/Order');
        $res = $m->where("scene_id='" . $order['scene_id'] . "' AND rank>'" . $order['rank'] . "'")->order('rank')->select();
        $rs = array();
        foreach ($res as $val) {
            $data = array();
            $data['rank'] = $val['rank'] - 1;
            $rs[] = $m->where("order_id='" . $val['order_id'] . "'")->save($data);
        }
        return !in_array(false, $rs) ? true : false;
    }

    /**
     * 更新场次内顺序单的开拍时间
     * @param array $order 拍单详情
     * @return bool
     */
    public function resetOrderStartTime($order)
    {
        $m = D('ChannelThrift/Aums/Order');
        if (!$order['is_timing_order']) {
            $res = $m->alias('o')->join(C('DB_AUMS.DB_PREFIX') . "order_scene os on os.scene_id=o.scene_id")
                ->where("os.scene_id='" . $order['scene_id'] . "' AND o.rank>='" . $order['rank'] . "' and o.is_timing_order=0")
                ->order('o.rank')->select();
            $rs = array();
            foreach ($res as $val) {
                $data = array();
                $data['bidding_start_time'] = date("Y-m-d H:i:0", strtotime($val['bidding_start_time']) - $order['est_elapsed_time']);
                $rs[] = $m->where("order_id='" . $val['order_id'] . "'")->save($data);
            }
            return !in_array(false, $rs) ? true : false;
        }
        return true;
    }

    /**
     * 生成拍单，返回新的拍单id
     * @param    array $order 拍单信息
     * @return   int
     */
    public function createOrder($order)
    {

        $m = D('ChannelThrift/Aums/Order');
        //优先级
        $rank = $m->where(['scene_id' => $order['scene_id']])->max('rank');
        $order['rank'] = $rank + 1;
        //检查该车是否已有拍单，且拍单状态不为流拍和失败
        $where = [];
        $where['car_id'] = $order['car_id'];
        $where['status'] = ['neq', 12];
        $check = $m->field("order_id,status,fail_type")->where($where)->order("order_id DESC")->find();
        if (!empty($check)) {
            if ($check['status'] != 2) {
                $code = 300003;
                $message = C('EXCEPTION_CODE.'.$code);
                throw new InvalidException(array('code' => $code, 'message' => $message));
            } else {
                $order['status'] = 1;
                $order['last_time'] = date('Y-m-d H:i:s');
                $m->where(['order_id' => $check['order_id']])->save($order);
                $orderId = $check['order_id'];
                $msg = "重上驳回的拍单:order_id:" . $check['order_id'];
            }
        } else {  //正常上拍
            //加锁解决并发问题，防此生成相同编号
            $redis = new PhpRedis();
            $max_order_id = $m->max('order_id');
            $keyArr = [
                'max_order_id' => $max_order_id,
            ];
            $keyName = getRedisKeyByCode('REDIS_KEY','100016',$keyArr);
            $lock = $redis->lock($keyName);
            if (!$lock) {
                make_throw('300004');
            }
            $order['order_no'] = gen_order_no();
            $order['create_time'] = date('Y-m-d H:i:s');
            $orderId = $m->add($order);
            //解锁
            $redis->unlock($keyName);

            if (!$orderId) {
                make_throw('300005');
            }
            $msg = "生成新的拍单：order_id:" . $orderId;
            //更改车源状态为5(拍卖中)
            $car = new CarService();
            $car->update($order['car_id'],array('car_status' => '5'));
        }

        //操作日志
        $log = array(
            'car_id' => $order['car_id'],
            'order_id' => $orderId,
            'emp_id' => $order['emp_id'],
            'action' => $msg
        );
        SystemLogService::addlog($log);
        return $orderId;
    }

    /**
     * 添加拍单跟踪信息
     *
     * @param int $order_id
     * @param array $order_action_data
     *
     * @return int
     */
    public static function addOrderTraceLog($orderId, $orderActionData)
    {
        $orderTraceLog = [];
        $orderTrace = D('ChannelThrift/Aums/OrderTraceLogList');
        $orderTraceLog['order_id'] = $orderId;
        $om = D('ChannelThrift/Aums/Order');
        $car_id = $om->where(['order_id' => $orderId])->getField('car_id');
        $orderTraceLog['car_id'] = $car_id;
        $emp_id = $orderActionData['emp_id'];
        $employee = EmployeeService::user_info_id($emp_id);
        if (!empty($employee)) {
            $emp_name = $employee['real_name'];
        } else {
            $emp_name = '--';
        }
        $orderTraceLog['emp_id'] = $emp_id;
        $orderTraceLog['emp_name'] = $emp_name;
        $orderTraceLog['action_no'] = array_keys(C('ORDER_ACTION_NAME'), $orderActionData['action_name'])[0];
        $orderTraceLog['action_name'] = $orderActionData['action_name'];
        $orderTraceLog['createtime'] = microtime_time();
        $ok = $orderTrace->add($orderTraceLog);
        return $ok;
    }


    /**
     * 重置场内其它顺序单的开拍时间
     * @param $orderInfo
     */
    public function resetStartTime($orderInfo){
        $sql = "UPDATE au_order SET bidding_start_time = FROM_UNIXTIME((UNIX_TIMESTAMP(bidding_start_time)+30))
                  WHERE STATUS = 301 AND scene_id  = '".$orderInfo['scene_id']."' AND rank>'".$orderInfo['rank']."'";
        return $this->execute($sql);
    }


    /**
     * 拍单信息
     * @param $orderInfo
     */
    public function isFirstSeqOrder($orderInfo){
        $map                    =   [];
        $map['scene_id']        =   $orderInfo['scene_id'];
        $map['is_timing_order'] =   0;
        $map['rank']            =   ['egt',1];//0 是被驳回的拍单

        $order=$this->getOrderByMap($map,'rank ASC');
        if($orderInfo['order_id']!=$order['order_id']){
            return false;
        }
        return true;

    }

    /**
     * 处理违约重拍 -- 到平台确认
     * @param $orderId
     * @return bool
     */
    public function breachRedoPlatform($orderId){
        //获取拍单详情
        $orderService = new OrderService();
        $orderInfo = $orderService->getOrder($orderId);

        trace($orderId. " - " .$orderInfo['order_no'].'违约重拍处理','','INFO',true);

        $map = ['car_id'=>$orderInfo['car_id']];
        $oldOrderInfo = $orderService->getOrderByMap($map,'order_id DESC','1,1');
        $data = [];
        $data['first_money'] = $oldOrderInfo[0]['first_money'];
        $data['confirm_type'] = 1;
        $rs = $orderService->update($orderId,$data);
        return $rs;
    }

    /**
     * 处理自收重拍
     * @param $orderId
     * @param $success_dealer_id
     */
    public function selfReceiveRedo($orderId,$success_dealer_id){

        $rs = true;

        $orderService = new OrderService();
        $orderInfo = $orderService->getOrder($orderId);

        $car = new CarService();
        $carInfo = $car->getCar($orderInfo['car_id']);

        //拍单是否自收重拍
        if ($carInfo['is_self_receive'] == 1) {
            trace($orderId . " - " . $orderInfo['order_no'] . "自收重拍处理",'','INFO',true);
            $data = [];
            $data['confirm_type']=1;
            $rs = $orderService->update($orderId,$data);
        } else {
            //自收人拍得非违约重拍的车辆，才打上自收标签
            if ($carInfo['is_dealer_breach'] == 0) {

                $dealerServ = new CarDealerService();
                $dealer = $dealerServ->getCarDealer($success_dealer_id);
                if ($dealer['dealer_type'] == 1) {
                    trace($orderId . " - " . $orderInfo['order_no'] . "自收人拍得车辆处理",'','INFO',true);
                    $data = [];
                    $data['is_self_receive'] = 1;
                    $data['self_receive_dealer_id'] = $success_dealer_id;
                    $rs = $car->update($orderInfo['car_id'],$data);
                }
            }
        }
        return $rs;

    }

}
